#include <Adafruit_GFX.h> 
#include <Adafruit_TFTLCD.h>
#include <TouchScreen.h>
#include <SPI.h>
#include <SD.h>
File myFile;
#if defined(__SAM3X8E__)
    #undef __FlashStringHelper::F(string_literal)
    #define F(string_literal) string_literal
#endif

#define YP A3  // must be an analog pin, use "An" notation!   A3
#define XM A2  // must be an analog pin, use "An" notation! A2
#define YM 9  // can be a digital pin 9
#define XP 8   // can be a digital pin 8

//Don't forget if your touch function doesn't work check the values above it may be (A1 A2 7 6) resp
#define TS_MINX 176
#define TS_MINY 159
#define TS_MAXX 921
#define TS_MAXY 884
#define MINPRESSURE 10
#define MAXPRESSURE 1000


TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define SD_CS 10    // Set the chip select line to whatever you use

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, A4);

char x[]="0.bmp";
char r[]="1111.bmp";
char mainScreen[] = "mainscreen.bmp";
char s[50] = "";
int val = 0;
int pressedFlag = 0;

void deleteFile() { myFile = SD.open("input.txt"); if (myFile) {SD.remove("input.txt"); delay(300);Serial.println("Deleted");}myFile.close(); }
void resetDevice(){ myFile = SD.open("input.txt"); if (myFile) {SD.remove("input.txt"); delay(300); myFile.close(); writeToFiles("N");}}
void readFile(){
  myFile = SD.open("input.txt"); 
  char letter; 
  String  chu="";
  if (myFile)
  {
    while (myFile.available()) 
    { 
      letter = myFile.read(); //read next character from file
      if(letter != '\n')
      {
        if(letter == 'N') { val = 0; }
        else {chu+=letter;}
      }
      delay(300);
    }
    val = (chu.toInt());
    Serial.println(chu);
    myFile.close(); 
  }
  else { writeToFiles("N");}
}
void readQuotesFile(){
  
}

void writeToFiles(String datas){
  deleteFile();
  myFile = SD.open("input.txt",FILE_WRITE);
  if (myFile) 
  { 
    myFile.print(datas);   
    
  }
  delay(300);
  myFile.close();
}
void setup(){
  Serial.begin(9600);
  tft.reset();
  uint16_t identifier = tft.readID();
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  tft.begin(identifier);
  if (!SD.begin(SD_CS)) { progmemPrintln(PSTR("failed!")); return;}
  tft.setRotation(3); 
  readFile();
  bmpDraw(x, 0, 0); 
  mainFunction(); 
}

void displayQuotes()
{
  bmpDraw(s, 0, 0);
  delay(300);
  writeToFiles(String(val+1));
}
void displayPhotos()
{
   int j=0;
   while(j!=5)
   {
    for(int i=1000;i<1010;i++)
    {
      (String(i)+".bmp").toCharArray(s,50);
       bmpDraw(s, 0, 0);
       delay(3000);
    }
   }
   delay(300);   
}
void mainFunction(){
  while(pressedFlag==0)
  {
      TSPoint p = ts.getPoint();       //checking if the user touched the screen
      pinMode(XM, OUTPUT);
      pinMode(YP, OUTPUT);
      if (p.z > MINPRESSURE && p.z < MAXPRESSURE) 
      { 
        p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());  
        p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
        Serial.print(p.x);Serial.print(" ");Serial.print(p.y);Serial.println();
        if(p.y > 40 && p.y < 158 )
        {   
          pressedFlag = 1;
          (String(val)+".bmp").toCharArray(s,50);
          displayQuotes();
          Serial.println(s);
        
        }
        else if( (p.x >10 && p.x <270) && (p.y >0 && p.y <10))
        {
          pressedFlag = 1;
          writeToFiles(String(1));
          Serial.print("Reset");
          bmpDraw(r, 0, 0); 
          delay(1200);
          bmpDraw(x, 0, 0); 
          
        }
      }    
  }
}

void loop(){}

#define BUFFPIXEL 40        //Printing speed 20 is meant to be the best, you can go to 60 but using too much RAM
void bmpDraw(char *filename, int x, int y) {

  File     bmpFile;
  int      bmpWidth, bmpHeight;   // W+H in pixels
  uint8_t  bmpDepth;              // Bit depth (currently must be 24)
  uint32_t bmpImageoffset;        // Start of image data in file
  uint32_t rowSize;               // Not always = bmpWidth; may have padding
  uint8_t  sdbuffer[3*BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
  uint16_t lcdbuffer[BUFFPIXEL];  // pixel out buffer (16-bit per pixel)
  uint8_t  buffidx = sizeof(sdbuffer); // Current position in sdbuffer
  boolean  goodBmp = false;       // Set to true on valid header parse
  boolean  flip    = true;        // BMP is stored bottom-to-top
  int      w, h, row, col;
  uint8_t  r, g, b;
  uint32_t pos = 0, startTime = millis();
  uint8_t  lcdidx = 0;
  boolean  first = true;

  if((x >= tft.width()) || (y >= tft.height())) return;

  Serial.println();
  progmemPrint(PSTR("Loading image '"));
  Serial.print(filename);
  Serial.println('\'');
  // Open requested file on SD card
  if ((bmpFile = SD.open(filename)) == NULL) {
    progmemPrintln(PSTR("File not found"));
    return;
  }

  // Parse BMP header
  if(read16(bmpFile) == 0x4D42) { // BMP signature
    progmemPrint(PSTR("File size: ")); Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    progmemPrint(PSTR("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    progmemPrint(PSTR("Header size: ")); Serial.println(read32(bmpFile));
    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      progmemPrint(PSTR("Bit Depth: ")); Serial.println(bmpDepth);
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!
        progmemPrint(PSTR("Image size: "));
        Serial.print(bmpWidth);
        Serial.print('x');
        Serial.println(bmpHeight);

        // BMP rows are padded (if needed) to 4-byte boundary
        rowSize = (bmpWidth * 3 + 3) & ~3;

        // If bmpHeight is negative, image is in top-down order.
        // This is not canon but has been observed in the wild.
        if(bmpHeight < 0) {
          bmpHeight = -bmpHeight;
          flip      = false;
        }

        // Crop area to be loaded
        w = bmpWidth;
        h = bmpHeight;
        if((x+w-1) >= tft.width())  w = tft.width()  - x;
        if((y+h-1) >= tft.height()) h = tft.height() - y;

        // Set TFT address window to clipped image bounds
        tft.setAddrWindow(x, y, x+w-1, y+h-1);

        for (row=0; row<h; row++) { // For each scanline...
          // Seek to start of scan line.  It might seem labor-
          // intensive to be doing this on every line, but this
          // method covers a lot of gritty details like cropping
          // and scanline padding.  Also, the seek only takes
          // place if the file position actually needs to change
          // (avoids a lot of cluster math in SD library).
          if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
            pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
          else     // Bitmap is stored top-to-bottom
            pos = bmpImageoffset + row * rowSize;
          if(bmpFile.position() != pos) { // Need seek?
            bmpFile.seek(pos);
            buffidx = sizeof(sdbuffer); // Force buffer reload
          }

          for (col=0; col<w; col++) { // For each column...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              // Push LCD buffer to the display first
              if(lcdidx > 0) {
                tft.pushColors(lcdbuffer, lcdidx, first);
                lcdidx = 0;
                first  = false;
              }
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
            }

            // Convert pixel from BMP to TFT format
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
            lcdbuffer[lcdidx++] = tft.color565(r,g,b);
          } // end pixel
        } // end scanline
        // Write any remaining data to LCD
        if(lcdidx > 0) {
          tft.pushColors(lcdbuffer, lcdidx, first);
        } 
        progmemPrint(PSTR("Loaded in "));
        Serial.print(millis() - startTime);
        Serial.println(" ms");
      } // end goodBmp
    }
  }

  bmpFile.close();
  if(!goodBmp) progmemPrintln(PSTR("BMP format not recognized."));
}
uint16_t read16(File f) {
  uint16_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read(); // MSB
  return result;
}
uint32_t read32(File f) {
  uint32_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read();
  ((uint8_t *)&result)[2] = f.read();
  ((uint8_t *)&result)[3] = f.read(); // MSB
  return result;
}
void progmemPrint(const char *str) {  char c; while(c = pgm_read_byte(str++)) Serial.print(c);}
void progmemPrintln(const char *str) { progmemPrint(str); Serial.println();}
